home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / 1.098 / mach / sun4c.md / machTrap.s < prev    next >
Text File  |  1991-08-02  |  55KB  |  1,679 lines

  1. /*
  2.  * machTrap.s --
  3.  *
  4.  *    Traps for sun4.
  5.  *
  6.  * Copyright 1989 Regents of the University of California
  7.  * Permission to use, copy, modify, and distribute this
  8.  * software and its documentation for any purpose and without
  9.  * fee is hereby granted, provided that the above copyright
  10.  * notice appear in all copies.  The University of California
  11.  * makes no representations about the suitability of this
  12.  * software for any purpose.  It is provided "as is" without
  13.  * express or implied warranty.
  14.  */
  15.  
  16. .seg    "data"
  17. .asciz    "$Header: /sprite/src/kernel/mach/sun4.md/RCS/machTrap.s,v 9.12 91/08/02 18:41:59 mgbaker Exp $ SPRITE (Berkeley)"
  18. .align    8
  19. .seg    "text"
  20.  
  21. #include "user/proc.h"
  22. #include "machConst.h"
  23. #include "machAsmDefs.h"
  24.  
  25. .align    8
  26. .seg    "text"
  27.  
  28. /*
  29.  * ----------------------------------------------------------------------
  30.  *
  31.  * MachTrap --
  32.  *
  33.  *    All traps except window overflow and window underflow go through
  34.  *    this trap handler.  This handler is used to save the appropriate
  35.  *    state, set up the kernel stack, and then jump to the correct
  36.  *    handler depending on the type of trap.  The handler assumes that
  37.  *    we have saved the trap %psr into %CUR_PSR_REG before we get here (as
  38.  *    an instruction in the vector table that made us branch here).
  39.  *
  40.  *    Window overflow and underflow jump directly from the vector table
  41.  *    to their handlers, since in the most common cases they do not need
  42.  *    to save state and they should be as fast as possible.
  43.  *
  44.  *    The scheme of things:
  45.  *
  46.  *    1) Check to see if we're in an invalid window.  If so, deal first with
  47.  *    window overflow.
  48.  *    2) Now that it's safe to overwrite our out registers, update the stack
  49.  *    pointer.  If coming from user mode, this means pulling the kernel
  50.  *    stack pointer out of the state structure and adding the appropriate
  51.  *    amount.  Otherwise, it means just means adding the appropriate amount to
  52.  *    our %fp.
  53.  *    3) Save the rest of the trap state (globals) to the stack.  Note that
  54.  *    although locals and ins contain trap state (ins are our caller's outs
  55.  *    which we shouldn't mess up, and the psr and other state registers are
  56.  *    in our locals) we need not save them explicitly, since they will be
  57.  *    saved as a part of the normal window overflow and underflow.  There
  58.  *    are exceptions to this, such as context switching or debugger traps,
  59.  *    where we must explicitly save the window to the stack, but the
  60.  *    exceptions must take care of this for themselves.
  61.  *    4) Re-enable traps and disable interrupts.  Traps must be disabled
  62.  *    so that if we get another window overflow or underflow,
  63.  *    we'll be able to deal with it.
  64.  *    5) Figure out what handler to call and call it.
  65.  *
  66.  *    The handler must call our return-from-trap post-amble, rather than
  67.  *    return here.
  68.  *
  69.  *    If a window underflow or overflow trap discovers that it must do
  70.  *    something tricky, such as call Vm_PageIn, that requires turning
  71.  *    on traps and interrupts, then it will call MachTrap to save state
  72.  *    for it.  This is why there are entries in MachTrap for window
  73.  *    overflow and underflow.  These are the entries to take care of the
  74.  *    "slow trap" overflows and underflows.
  75.  *
  76.  * Results:
  77.  *    None.
  78.  *
  79.  * Side effects:
  80.  *    We make space on our kernel stack to save this trap window.
  81.  *    If it is a user process entering the kernel, then we make its trapRegs
  82.  *    field point to this save-window area on the kernel stack.
  83.  *
  84.  * ----------------------------------------------------------------------
  85.  */
  86. .global    _MachTrap
  87. _MachTrap:
  88.     /*
  89.      * Save the state registers.  This is safe, since we're saving them
  90.      * to local registers and we can do this even if we've entered
  91.      * into an invalid window.
  92.      * In the vector table that jumps here, we have already saved
  93.      * the %psr into %CUR_PSR_REG.  The trap instruction itself saved
  94.      * the trap pc and next pc into local registers %CUR_PC_REG and
  95.      * %NEXT_PC_REG.  This means we must save only the %tbr and the %y
  96.      * registers.
  97.      */
  98.     mov    %tbr, %CUR_TBR_REG
  99.     mov    %y, %CUR_Y_REG
  100.     /*
  101.      * Are we in an invalid window?
  102.      */
  103.     MACH_INVALID_WINDOW_TEST()
  104.     be    WindowOkay
  105.     nop
  106.     /*
  107.      * Deal with window overflow - put return addr in SAFE_TEMP since
  108.      * the overflow handler will look for the return address there..
  109.      * It is okay to do this, even if we got here after due to a slow
  110.      * overflow trap due to special action needed, because if we did that,
  111.      * then we've already taken care of the overflow problem and so we
  112.      * won't get it here and so we won't be overwriting the return address
  113.      * in SAFE_TEMP.
  114.      */
  115.     set    MachWindowOverflow, %VOL_TEMP1
  116.     jmpl    %VOL_TEMP1, %SAFE_TEMP
  117.     nop
  118. WindowOkay:
  119.     /*
  120.      * Now that we know our out registers are safe to use, since we're
  121.      * in a valid window, update our stack  pointer.
  122.      * If coming from user mode, I need to get kernel sp from
  123.      * state structure.  If we came from kernel
  124.      * mode, just subtract a stack frame from the current frame pointer and
  125.      * continue. To see if we came from user mode, we look at the
  126.      * previous state bit (PS) in the processor state register.
  127.      * I set up the stack pointer in the delay slot of the branch if I came
  128.      * from kernel mode, so it's as fast as possible.  I annul the
  129.      * instruction if it turns out to be a user stack.
  130.      * We must give the stack a full state frame so that C routines
  131.      * we call will have space to store their arguments.  (System calls,
  132.      * for example!)
  133.      *
  134.      * NOTE: The amount we bump up the stack by here must
  135.      * agree with the debugger stack test in the window underflow routine,
  136.      * so that we don't trash our stack when returning from the
  137.      * debugger!!!!!
  138.      */
  139.         andcc   %CUR_PSR_REG, MACH_PS_BIT, %g0         /* previous state? */
  140.         bne,a   DoneWithUserStuff             /* was kernel mode */
  141.         add     %fp, -MACH_SAVED_STATE_FRAME, %sp     /* set kernel sp */
  142.     MACH_GET_CUR_STATE_PTR(%VOL_TEMP2, %VOL_TEMP1)    /* into %VOL_TEMP2 */
  143.         add     %VOL_TEMP2, MACH_KSP_OFFSET, %VOL_TEMP1 /* &(machPtr->ksp) */
  144.         ld      [%VOL_TEMP1], %sp             /* machPtr->ksp */
  145.     set    (MACH_KERN_STACK_SIZE - MACH_SAVED_STATE_FRAME), %VOL_TEMP1
  146.         add     %sp, %VOL_TEMP1, %sp 
  147.     /*
  148.      * Since we came from user mode, set the trapRegs field of the
  149.      * current state structure to the value of our new kernel sp,
  150.      * since the trap regs are saved on top of the stack.
  151.      */
  152.     add    %VOL_TEMP2, MACH_TRAP_REGS_OFFSET, %VOL_TEMP2
  153.     st    %sp, [%VOL_TEMP2]
  154.  
  155. DoneWithUserStuff:
  156.     /* Test stack alignment here?? */
  157.  
  158.     /*
  159.      * This only saves the globals to the stack.  The locals
  160.      * and ins make it there through normal overflow and underflow.
  161.      *
  162.      * NOTE that we cannot trash %g1 even after saving the global
  163.      * registers, since that is the register that contains the system
  164.      * call number for system call traps!
  165.      */
  166.     MACH_SAVE_GLOBAL_STATE()
  167.  
  168.     /* traps on, maskable interrupts off */
  169.     MACH_SR_HIGHPRIO()
  170.  
  171.     /*
  172.      * It is tedious to do all these serial comparisons against the
  173.      * trap type, so this should be changed to a jump table.  It's this
  174.      * way right now because I'm working on other things and this is
  175.      * easy for debugging.
  176.      */
  177.     and    %CUR_TBR_REG, MACH_TRAP_TYPE_MASK, %VOL_TEMP1 /* get trap */
  178.  
  179.     cmp    %VOL_TEMP1, MACH_LEVEL0_INT
  180.     bl    NotAnInterrupt
  181.     nop
  182.     cmp    %VOL_TEMP1, MACH_LEVEL15_INT
  183.     bgu    NotAnInterrupt
  184.     nop
  185.     /*
  186.      * It's an interrupt.
  187.      */
  188.     b    MachHandleInterrupt
  189.     nop
  190.  
  191. NotAnInterrupt:
  192.  
  193.     cmp    %VOL_TEMP1, MACH_TRAP_SYSCALL        /* system call */
  194.     be    MachSyscallTrap
  195.     nop
  196.  
  197.     cmp    %VOL_TEMP1, MACH_INSTR_ACCESS        /* instruction fault */
  198.     be    MachHandlePageFault
  199.     nop
  200.  
  201.     cmp    %VOL_TEMP1, MACH_DATA_ACCESS        /* data fault */
  202.     be    MachHandlePageFault
  203.     nop
  204.  
  205.     cmp    %VOL_TEMP1, MACH_TRAP_SIG_RETURN    /* ret from handler */
  206.     be    _MachReturnFromSignal
  207.     nop
  208.  
  209.     cmp    %VOL_TEMP1, MACH_TRAP_FLUSH_WINDOWS    /* flush window trap */
  210.     be    MachFlushWindowsToStackTrap
  211.     nop
  212.  
  213.     cmp    %VOL_TEMP1, MACH_TRAP_UNIX_SYSCALL    /* unix syscall */
  214.     be    MachUnixSyscallTrap
  215.     nop
  216.  
  217.     cmp    %VOL_TEMP1, MACH_TRAP_INSTR_2        /* Dynamic linking  */
  218.     be    MachLinkTrap
  219.     nop
  220.  
  221.     /*
  222.      * These next few are handled by C routines, and we want them to
  223.      * return to MachReturnFromTrap, so set that address as the return pc.
  224.      */
  225.     cmp    %VOL_TEMP1, MACH_ILLEGAL_INSTR        /* illegal instr */
  226.     set    _MachReturnFromTrap, %RETURN_ADDR_REG    /* set return pc */
  227.     mov    %VOL_TEMP1, %o0
  228.     mov    %CUR_PC_REG, %o1
  229.     mov    %CUR_PSR_REG, %o2
  230.     be    _MachHandleTrap        /* C routine */
  231.     nop
  232.  
  233.     cmp    %VOL_TEMP1, MACH_PRIV_INSTR        /* privileged instr */
  234.     set    _MachReturnFromTrap, %RETURN_ADDR_REG    /* set return pc */
  235.     mov    %VOL_TEMP1, %o0
  236.     mov    %CUR_PC_REG, %o1
  237.     mov    %CUR_PSR_REG, %o2
  238.     be    _MachHandleTrap        /* C routine */
  239.     nop
  240.  
  241.     cmp    %VOL_TEMP1, MACH_MEM_ADDR_ALIGN        /* addr not aligned */
  242.     set    _MachReturnFromTrap, %RETURN_ADDR_REG    /* set return pc */
  243.     mov    %VOL_TEMP1, %o0
  244.     mov    %CUR_PC_REG, %o1
  245.     mov    %CUR_PSR_REG, %o2
  246.     be    _MachHandleTrap        /* C routine */
  247.     nop
  248.  
  249.     cmp    %VOL_TEMP1, MACH_TAG_OVERFLOW        /* tagged instr ovfl */
  250.     set    _MachReturnFromTrap, %RETURN_ADDR_REG    /* set return pc */
  251.     mov    %VOL_TEMP1, %o0
  252.     mov    %CUR_PC_REG, %o1
  253.     mov    %CUR_PSR_REG, %o2
  254.     be    _MachHandleTrap        /* C routine */
  255.     nop
  256.  
  257.     cmp    %VOL_TEMP1, MACH_FP_EXCEP        /* fp unit badness */
  258.     set    _MachReturnFromTrap, %RETURN_ADDR_REG    /* set return pc */
  259.     mov    %VOL_TEMP1, %o0
  260.     mov    %CUR_PC_REG, %o1
  261.     mov    %CUR_PSR_REG, %o2
  262.     be    _MachHandleTrap        /* C routine */
  263.     nop
  264.  
  265.     cmp    %VOL_TEMP1, MACH_FP_DISABLED        /* fp unit disabled */
  266.     set    _MachReturnFromTrap, %RETURN_ADDR_REG    /* set return pc */
  267.     mov    %VOL_TEMP1, %o0
  268.     mov    %CUR_PC_REG, %o1
  269.     mov    %CUR_PSR_REG, %o2
  270.     be    _MachHandleTrap        /* C routine */
  271.     nop
  272.  
  273.     /*
  274.      * We never get here directly from the window overflow trap.
  275.      * Instead, what this means is that after handling a window
  276.      * overflow trap, on the way out we had to deal with a special
  277.      * user action.  Because we don't save state, etc, on a regular
  278.      * window overflow, we've executed the above code to save the
  279.      * state for us.  Now we just want to go back and deal with the
  280.      * special overflow.
  281.      */
  282.     cmp    %VOL_TEMP1, MACH_WINDOW_OVERFLOW    /* weird overflow */
  283.     be    MachReturnToOverflowWithSavedState
  284.     nop
  285.  
  286.     cmp    %VOL_TEMP1, MACH_WINDOW_UNDERFLOW    /* weird underflow */
  287.     be    MachReturnToUnderflowWithSavedState
  288.     nop
  289.  
  290.     cmp    %VOL_TEMP1, MACH_TRAP_DEBUGGER        /* enter debugger */
  291.     be    _MachHandleDebugTrap
  292.     nop
  293.  
  294.     b    _MachHandleDebugTrap        /* all  others to debugger */
  295.     nop
  296.  
  297.  
  298. /*
  299.  * ----------------------------------------------------------------------
  300.  *
  301.  * MachReturnFromTrap --
  302.  *
  303.  *    Go through the inverse of MachTrap.  The trap handlers that MachTrap
  304.  *    called return to here rather than MachTrap.
  305.  *
  306.  *    The scheme of things:
  307.  *
  308.  *    1) Determine if we are returning to user mode.  If so, then we must
  309.  *    check the specialHandling flag.  If it is set, then we must call
  310.  *    MachUserAction.
  311.  *    2) If we called MachUserAction, then we must check its return value
  312.  *    to see if we need to deal with any signals.  If we do, then
  313.  *    we call MachHandleSignal().  It returns to user mode itself via
  314.  *    a rett instruction, so we don't come back here until the
  315.  *    return-from-signal trap that the user ends up executing to return to
  316.  *    the kernel from a signal.
  317.  *    3) For both returns to user mode and returns to kernel mode, we
  318.  *    must next check if we would return to an invalid window.  If so,
  319.  *    we must make it valid or we will get a watchdog reset.  We may
  320.  *    call the window underflow routine to do this.  But, if we are
  321.  *    returning to user mode, we must check to make sure the user stack
  322.  *    is resident, since the underflow routine can't get any page faults.
  323.  *    If the user stack isn't resident, we page it in.
  324.  *    4) Finally, we disable traps again (or the rett instruction will
  325.  *    give us a watchdog reset), restore the global registers, restore
  326.  *    the %tbr, %y registers, restore the %psr to the trap psr, and rett
  327.  *    (return from trap) to the saved trap pc and next pc.
  328.  *
  329.  * Results:
  330.  *    None.
  331.  *
  332.  * Side effects:
  333.  *    We jump back to where we came from.  If we came from a system call
  334.  *    or certain other traps, we'll actually return to where we came from
  335.  *    plus 8, or else we would re-execute the system call instruction.
  336.  *    The addition of 8 was done by the individual handlers that know
  337.  *    whether or not they would need to do this.
  338.  *
  339.  *    If a user process has a bad stack pointer, we will kill it here and
  340.  *    print out a message.
  341.  *
  342.  * ----------------------------------------------------------------------
  343.  */
  344. .global    _MachReturnFromTrap
  345. _MachReturnFromTrap:
  346.     /* Are we a user or kernel process? */
  347.     andcc    %CUR_PSR_REG, MACH_PS_BIT, %g0
  348.     bne    NormalReturn
  349.     nop
  350.     /* Do we need to take a special action? Check special handling flag. */
  351.     MACH_GET_CUR_PROC_PTR(%VOL_TEMP1)
  352.     set    _machSpecialHandlingOffset, %VOL_TEMP2
  353.     ld    [%VOL_TEMP2], %VOL_TEMP2
  354.     add    %VOL_TEMP1, %VOL_TEMP2, %VOL_TEMP1
  355.     ld    [%VOL_TEMP1], %VOL_TEMP1
  356.     tst    %VOL_TEMP1
  357.     be    NormalReturn
  358.     nop
  359.     call    _MachUserAction
  360.     nop
  361.     /* Check if we must handle a signal */
  362.     tst    %RETURN_VAL_REG
  363.     be    NormalReturn
  364.     nop
  365.     cmp    %RETURN_VAL_REG, 2
  366.     be    DoUnixSignal
  367.     nop
  368.     /*
  369.      * We must handle a signal.  Call the leaf routine MachSetupSignal.
  370.      * It does its own return from trap, so we don't come back here when
  371.      * it's done!
  372.      */
  373.     call    _MachHandleSignal
  374.     nop
  375. DoUnixSignal:
  376.     MACH_RESTORE_WINDOW_FROM_STACK()
  377.     nop
  378.     sub    %fp, 0x8f0, %fp
  379.     nop
  380. NormalReturn:
  381.     MACH_UNDERFLOW_TEST(testModuloLabel)
  382.     be    UnderflowOkay
  383.     nop
  384.     /*
  385.      * Make sure stack is resident.  We don't want to get a page
  386.      * fault in the underflow routine, because it moves into the window
  387.      * to restore and so its calls to Vm code would move into this
  388.      * window and overwrite it!  First check if it's a user process, since
  389.      * that should be the only case where the stack isn't resident.
  390.      */
  391.     andcc    %CUR_PSR_REG, MACH_PS_BIT, %g0
  392.     bne    CallUnderflow
  393.     nop
  394.     /*
  395.      * It's a user process, so check residence and protection fields of pte.
  396.      * Before anything we check stack alignment.
  397.      */
  398.     andcc    %fp, 0x7, %g0
  399.     bne    KillUserProc
  400.     nop
  401.     MACH_CHECK_FOR_FAULT(%fp, %VOL_TEMP1)
  402.     be    CheckNextFault
  403.     nop
  404.     /*
  405.      * Call VM Stuff with the %fp which will be stack pointer in
  406.      * the window we restore.
  407.      */
  408.     QUICK_ENABLE_INTR(%VOL_TEMP1)
  409.     mov    %fp, %o0
  410.     clr    %o1        /* also check for protection????? */
  411.     call    _Vm_PageIn, 2
  412.     nop
  413.     QUICK_DISABLE_INTR(%VOL_TEMP1)
  414.     tst    %RETURN_VAL_REG
  415.     bne    KillUserProc
  416.     nop
  417. CheckNextFault:
  418.     /* Check other extreme of area we'd touch */
  419.     add    %fp, (MACH_SAVED_WINDOW_SIZE - 4), %o0
  420.     MACH_CHECK_FOR_FAULT(%o0, %VOL_TEMP1)
  421.     be    CallUnderflow
  422.     nop
  423.     QUICK_ENABLE_INTR(%VOL_TEMP1)
  424.     clr    %o1
  425.     call    _Vm_PageIn, 2
  426.     nop
  427.     QUICK_DISABLE_INTR(%VOL_TEMP1)
  428.     tst    %RETURN_VAL_REG
  429.     be    CallUnderflow
  430.     nop
  431. KillUserProc:
  432.     /*
  433.      * Kill user process!  Its stack is bad.
  434.      */
  435.     MACH_SR_HIGHPRIO()    /* traps back on for overflow from printf */
  436.     set    _MachReturnFromTrapDeathString, %o0
  437.     call    _printf, 1
  438.     nop
  439.     MACH_GET_CUR_PROC_PTR(%o0)        /* procPtr in %o0 */
  440.         set     _machGenFlagsOffset, %o1 
  441.         ld      [%o1], %o1
  442.         add     %o0, %o1, %o1
  443.         ld      [%o1], %o1
  444.         set     _machForeignFlag, %o2
  445.         ld      [%o2], %o2
  446.         andcc   %o1, %o2, %o1                   /* Is this a migrated proc? */
  447.         be      DebugIt
  448.         nop
  449.     set    PROC_TERM_DESTROYED, %o0    /* If so, kill it. */
  450.     set    PROC_BAD_STACK, %o1
  451.     clr    %o2
  452.     call    _Proc_ExitInt, 3
  453.     nop
  454. DebugIt:                    /* Else, make it debuggable. */
  455.     MACH_GET_CUR_PROC_PTR(%o0)        /* procPtr in %o0 */
  456.     call    _Sig_CheckForKill, 1        /* kill proc if KILL signal */
  457.     nop
  458.     MACH_GET_CUR_PROC_PTR(%o0)        /* procPtr in %o0 */
  459.     set    TRUE, %o1            /* debug TRUE */
  460.     set    PROC_TERM_DESTROYED, %o2
  461.     set    PROC_BAD_STACK, %o3
  462.     clr    %o4
  463.     call    _Proc_SuspendProcess, 5
  464.     nop
  465.     ba    DebugIt            /* proc should loop if continued */
  466.     nop
  467.  
  468. CallUnderflow:
  469.     set    MachWindowUnderflow, %VOL_TEMP1
  470.     jmpl    %VOL_TEMP1, %RETURN_ADDR_REG
  471.     nop
  472. UnderflowOkay:
  473.     MACH_DISABLE_TRAPS(%VOL_TEMP1, %VOL_TEMP2)
  474.     MACH_RESTORE_GLOBAL_STATE()
  475.     /* restore y reg */
  476.     mov    %CUR_Y_REG, %y
  477.  
  478.     /* restore tbr reg */
  479.     mov    %CUR_TBR_REG, %tbr
  480.     /* restore psr */
  481.     MACH_RESTORE_PSR()
  482.     jmp    %CUR_PC_REG
  483.     rett    %NEXT_PC_REG
  484.     nop
  485.  
  486. /*
  487.  * ----------------------------------------------------------------------
  488.  *
  489.  * MachHandleWindowOverflowTrap --
  490.  *
  491.  *    Trap entrance to the window overflow handler.  We try to get in and
  492.  *    out of here as quickly as possible in the normal case.  Unlike
  493.  *    most traps, we jump here directly from the trap table, and do not
  494.  *    go through the usual MachTrap preamble.  This means no
  495.  *    state has been saved and we have no stack pointer.  This in turn means
  496.  *    that we cannot turn traps on, since we have no saved state and no place
  497.  *    to save the trap registers. This routine sets up a return
  498.  *    address, calls the overflow handler, restores the psr, and
  499.  *    returns from the trap.  It assumes that the trap psr was stored in
  500.  *    %CUR_PSR_REG before jumping here (in the trap vector table).
  501.  *
  502.  *    When we return to this routine from the actual overflow handling
  503.  *    routine, we check to see if we're returning to user mode.  If we aren't
  504.  *    we can just leave this routine normally.  If we're returning to user
  505.  *    mode, however, we must check for some special cases.  It may be that
  506.  *    the user stack wasn't resident and that we had to save the overflow
  507.  *    window to a special internal buffer rather than the user stack.  If this
  508.  *    is so, we require extra processing.  So we call MachTrap to save state
  509.  *    for us and then call MachReturnFromTrap, which will handle the fact
  510.  *    that the window was saved to an internal buffer.  The effect of all of
  511.  *    this is to turn the overflow trap into a "slow overflow trap" that goes
  512.  *    through the usual trap preamble and postamble.
  513.  *
  514.  * Results:
  515.  *    None.
  516.  *
  517.  * Side effects:
  518.  *    The mach state structure may be modified if this is a user window
  519.  *    and its stack isn't resident, causing us to save the window to
  520.  *    the buffers in the mach state structure.
  521.  *
  522.  * ----------------------------------------------------------------------
  523.  */
  524. .global    MachHandleWindowOverflowTrap
  525. MachHandleWindowOverflowTrap:
  526.     /*
  527.      * Call actual overflow handler.
  528.      */
  529.     set    MachWindowOverflow, %VOL_TEMP1
  530.     jmpl    %VOL_TEMP1, %SAFE_TEMP
  531.     nop
  532.     /*
  533.      * If returning to user mode, check special handling flags here to
  534.      * see if we need to do any fancy processing (due to the user's
  535.      * stack not being resident so we had to save the window to an internal
  536.      * buffer instead).
  537.      */
  538.         andcc   %CUR_PSR_REG, MACH_PS_BIT, %g0        /* user or kernel? */
  539.         bne     NormalOverflowReturn
  540.         nop
  541.         /* Do we need to take a special action? Check special handling flag. */
  542.     MACH_GET_CUR_PROC_PTR(%VOL_TEMP1)
  543.         set     _machSpecialHandlingOffset, %VOL_TEMP2
  544.         ld      [%VOL_TEMP2], %VOL_TEMP2
  545.         add     %VOL_TEMP1, %VOL_TEMP2, %VOL_TEMP1
  546.         ld      [%VOL_TEMP1], %VOL_TEMP1
  547.         tst     %VOL_TEMP1
  548.         be      NormalOverflowReturn
  549.     nop
  550.     /*
  551.      * We need to save state and allocate space on the stack, etc.
  552.      * Run through regular trap preamble to do this.  The trap preamble
  553.      * will then return us to here.  This is all in preparation for
  554.      * calling MachReturnFromTrap, since that will call MachUserAction
  555.      * to deal with the window saved to the internal buffer.
  556.      */
  557.     call    _MachTrap
  558.     nop
  559. MachReturnToOverflowWithSavedState:
  560.     /*
  561.      * Now call trap postamble to restore state and push saved window to
  562.      * the user stack.  MachReturnFromTrap will return to user mode, so
  563.      * we will not come back here after this call!
  564.      */
  565.     call    _MachReturnFromTrap
  566.     nop
  567.  
  568.     /*
  569.      * This was a normal fast window overflow trap, so just return.
  570.      */
  571. NormalOverflowReturn:
  572.     MACH_RESTORE_PSR()
  573.     jmp    %CUR_PC_REG
  574.     rett    %NEXT_PC_REG
  575.     nop
  576.  
  577. /*
  578.  * ----------------------------------------------------------------------
  579.  *
  580.  * MachWindowOverflow --
  581.  *
  582.  *    Window overflow handler.  It's set up so that it can be called from the
  583.  *    fast window overflow trap handler, or it can be called directly from
  584.  *    MachTrap for any trap that causes us to land inside an invalid window.
  585.  *
  586.  *    The window we've trapped into is currently invalid.  We want to
  587.  *    make it valid.  We do this by moving one window further, saving that
  588.  *    window to the stack, marking it as the new invalid window, and then
  589.  *    moving back to the window that we trapped into.  It is then valid
  590.  *    and usable.  Note that we move first to the window to save and then
  591.  *    mark it invalid.  In the other order we would get another overflow
  592.  *    trap, but with traps turned off, which causes a watchdog reset...
  593.  *    Note that %sp should point to the lowest address usable
  594.  *    word in the current stack frame.  %fp is the %sp of the
  595.  *    caller's stack frame, so the first (highest in memory) usable word
  596.  *    of a current stack frame is (%fp - 4).
  597.  *
  598.  *    This code will be called with traps DISABLED, so nothing in this
  599.  *    code is allowed to cause a trap.  This means no procedure calls are
  600.  *    allowed.
  601.  *
  602.  * Results:
  603.  *    Returns to the address %SAFE_TEMP + 8.
  604.  *
  605.  * Side effects:
  606.  *    The window invalid mask changes and a register window is saved.
  607.  *    The mach state structure may change if we need to save this window
  608.  *    into its internal buffers (if it's a user window and the stack isn't
  609.  *    resident).
  610.  *
  611.  * ----------------------------------------------------------------------
  612.  */
  613. .global    MachWindowOverflow
  614. MachWindowOverflow:
  615.     /*
  616.      * We enter inside of an invalid window, so we can't use in registers,
  617.      * out registers or global registers to begin with.
  618.      * We temporarily clear out some globals since we won't be able to
  619.      * use locals in window we move to before saving it.  Using them would
  620.      * mess them up for window's owner.
  621.      */
  622.     mov    %g3, %VOL_TEMP1
  623.     mov    %g4, %VOL_TEMP2
  624.     save                /* move to the window to save */
  625.     MACH_ADVANCE_WIM(%g3, %g4)    /* reset %wim to current window */
  626.     /*
  627.      * If this is a user window, then see if stack space is resident.
  628.      * If it is, go ahead, but if not, then set special handling and
  629.      * save to buffers.  It's fairly dreadful that we must do all this
  630.      * checking here, since this will slow down all the overflow traps.
  631.      */
  632.     set    MACH_MAX_USER_STACK_ADDR, %g3    /* %sp in user space? */
  633.     subcc    %g3, %sp, %g0            /* need sp < highest addr */
  634.     bleu    NotUserStack
  635.     nop
  636.     set    MACH_FIRST_USER_ADDR, %g3    /* need sp >= lowest addr */
  637.     subcc    %sp, %g3, %g0
  638.     bgeu    UserStack
  639.     nop
  640. NotUserStack:
  641.     set    MACH_STACK_BOTTOM, %g3
  642.     subcc    %sp, %g3, %g0            /* need sp >= lowest addr */
  643.     blu    BadStack
  644.     nop
  645.     set    VMMACH_DEV_START_ADDR, %g3    /* need sp < highest addr */
  646.     subcc    %g3, %sp, %g0
  647.     bgu    NormalOverflow
  648.     nop
  649. BadStack:
  650.     /*
  651.      * Assume it was a user process's bad stack pointer.  We can't kill
  652.      * the process here, so just take over the window and the user process
  653.      * will die a terrible death later.  To take over the window, we just
  654.      * return, since we've already advanced the %wim.
  655.      */
  656.     ba    ReturnFromOverflow
  657.     nop
  658. UserStack:
  659.     /*
  660.      * If the stack alignment is bad, we just take over the window and
  661.      * assume the user process will die a horrible death later on.
  662.      */
  663.     andcc    %sp, 0x7, %g0
  664.     bne    ReturnFromOverflow
  665.     nop
  666.  
  667.     /* Would saving window cause a page fault? */
  668.     MACH_CHECK_FOR_FAULT(%sp, %g3)
  669.     bne    SaveToInternalBuffer
  670.     nop
  671.  
  672.     /* check other address extreme */
  673.     add    %sp, (MACH_SAVED_WINDOW_SIZE - 4), %g4
  674.     MACH_CHECK_FOR_FAULT(%g4, %g3)
  675.     be    NormalOverflow
  676.     nop
  677. SaveToInternalBuffer:
  678.     /*
  679.      * The stack wasn't resident, so we must save to an internal buffer
  680.      * and set the special handling flag.
  681.      * We update the saved mask to show that this window had to be saved
  682.      * to the internal buffers.  We do this by or'ing in the value of
  683.      * the current window invalid mask, since it's been set to point to
  684.      * this window we must save.
  685.      */
  686.     MACH_GET_CUR_STATE_PTR(%g3, %g4)    /* puts machStatePtr in %g3 */
  687.     set    _machCurStatePtr, %g4
  688.     st    %g3, [%g4]            /* update it */
  689.     add    %g3, MACH_SAVED_MASK_OFFSET, %g3
  690.     ld    [%g3], %g3
  691.     mov    %wim, %g4
  692.     or    %g3, %g4, %g4
  693.     set    _machCurStatePtr, %g3
  694.     ld    [%g3], %g3
  695.     add    %g3, MACH_SAVED_MASK_OFFSET, %g3
  696.     st    %g4, [%g3]
  697.  
  698.     /*
  699.      * Get and set the special handling flag in the current process state.
  700.      */
  701.     MACH_GET_CUR_PROC_PTR(%g3)
  702.     set    _machSpecialHandlingOffset, %g4
  703.     ld    [%g4], %g4
  704.     add    %g3, %g4, %g3
  705.     set    0x1, %g4
  706.     st    %g4, [%g3]
  707.  
  708.     /*
  709.      * Save the current user stack pointer for this window.
  710.      */
  711.     set    _machCurStatePtr, %g3
  712.     ld    [%g3], %g3
  713.     add    %g3, MACH_SAVED_SPS_OFFSET, %g3
  714.     mov    %psr, %g4
  715.     and    %g4, MACH_CWP_BITS, %g4
  716.     /* Multiply by 4 bytes per int */
  717.     sll    %g4, 2, %g4
  718.     add    %g3, %g4, %g3
  719.     st    %sp, [%g3]
  720.  
  721.     /*
  722.      * Now save to internal buffer.
  723.      */
  724.     set    _machCurStatePtr, %g3
  725.     ld    [%g3], %g3
  726.     add    %g3, MACH_SAVED_REGS_OFFSET, %g3
  727.     /*
  728.      * Current window * 4 bytes per reg is still in %g4.  Now we just
  729.      * need to multiply it by the number of registers per window.
  730.      */
  731.     sll    %g4, MACH_NUM_REG_SHIFT, %g4
  732.     add    %g3, %g4, %g3        /* offset to start saving at */
  733.     MACH_SAVE_WINDOW_TO_BUFFER(%g3)
  734.     set    ReturnFromOverflow, %g3
  735.     jmp    %g3
  736.     nop
  737. NormalOverflow:
  738.     /*
  739.      * Save this window to stack - save locals and ins to top 16 words
  740.      * on the stack. (Since our stack grows down, the top word is %sp
  741.      * and the bottom will be (%sp + offset).
  742.      */
  743.     MACH_SAVE_WINDOW_TO_STACK()
  744. ReturnFromOverflow:
  745.     restore                /* move back to trap window */
  746.     mov    %VOL_TEMP1, %g3        /* restore global registers */
  747.     mov    %VOL_TEMP2, %g4
  748.  
  749.     /*
  750.      * jump to calling routine - this may be a trap-handler or not.
  751.      */
  752.     jmp    %SAFE_TEMP + 8
  753.     nop
  754.  
  755. /*
  756.  * ----------------------------------------------------------------------
  757.  *
  758.  * MachHandleWindowUnderflowTrap --
  759.  *
  760.  *    Trap entrance to the window underflow handler.  This sets up a
  761.  *    return address, retreats a window, calls the underflow handler,
  762.  *    advances back to window in which we entered the routine, restores
  763.  *    the psr, and returns from the trap.  We must retreat a window since
  764.  *    on a trap we are 2 windows away from the window to restore, but
  765.  *    on returning from a trap and checking if we need to restore a window,
  766.  *    we are only one window away.  See the comments in MachWindowUnderflow()
  767.  *    for more details.
  768.  *    Because we must do some work in the window we were executing in when
  769.  *    we took a trap, we must make sure to save and restore the registers
  770.  *    we use there.  This means clearing two globals out for this purpose.
  771.  *    We save and restore the globals in the actual trap window, since we
  772.  *    know we can use the local registers there freely.  The underflow
  773.  *    routine expects its return address in %RETURN_ADDR_REG, so this is the
  774.  *    register we must save and restore in the inbetween window.
  775.  *
  776.  *    In the case where the window we're restoring is for a user process,
  777.  *    we must also check for whether the stack is resident and writable.
  778.  *    If it isn't, we must page it in.  To do this is gross.  Since the
  779.  *    trap window we've entered into is 2 windows away from the window to
  780.  *    restore, we must move back one window and check the %fp there.  (This
  781.  *    will be the %sp in the actual window to restore.)  If it isn't
  782.  *    resident, then we must move forward again to the trap window and call
  783.  *    MachTrap to save state for us. Then we can call the Vm_PageIn code
  784.  *    from the trap window to page in the nasty stuff.  If it fails, we
  785.  *    must kill the user process.  All of this is complicated a bit further
  786.  *    by the fact that we have 2 addresses to test: the %fp and the
  787.  *    %fp + the size of the saved window stuff. So we check both for
  788.  *    residence.  If both are okay, we just do normal underflow.  If one or
  789.  *    the other fails, we save state.  We then test the first address,
  790.  *    if it fails, we page it in.  Then if the second one fails, we also
  791.  *    page it in.  It most likely will have been paged in by the first one,
  792.  *    though.  Then, after all this, we call the normal underflow which
  793.  *    should then be protected from page faults.  It has to be, since
  794.  *    it operates in one window back from the trap window where we saved
  795.  *    state, and we can't have any calls to Vm code there overwriting our
  796.  *    saved state.  Then we return.  If we marked that we had to save
  797.  *    state, then we must restore state by calling MachReturnFromTrap and
  798.  *    leaving as if this had all been a slow trap instead.  Unfortunately,
  799.  *    we must test some stuff twice, since there are no registers to save
  800.  *    anything into (%VOL_TEMP registers are blasted by the MachTrap code,
  801.  *    and the SAFE_TEMP register is already used to mark whether we saved
  802.  *    state).
  803.  *
  804.  *    NOTE:  In the case where we must save state by calling MachTrap,
  805.  *    a lot of the underflow code is duplicated in MachReturnFromTrap,
  806.  *    which we also end up calling.  The reason I cannot simply call
  807.  *    MachReturnFrom trap then to do all that work, is that I must do the
  808.  *    work in one window away in the case of a real underflow trap.  There
  809.  *    may be a way to deal with this, but I haven't done it yet.
  810.  *
  811.  * Results:
  812.  *    None.
  813.  *
  814.  * Side effects:
  815.  *    The window in question is restored.
  816.  *
  817.  * ----------------------------------------------------------------------
  818.  */
  819. .global    MachHandleWindowUnderflowTrap
  820. MachHandleWindowUnderflowTrap:
  821.     /*
  822.      * We need a global to mark further actions, and a global to save
  823.      * the fp in if we find it needs to be page faulted.  We can save one
  824.      * global in SAFE_TEMP since it's only whacked by MachTrap, which is
  825.      * the only thing that might whack it, in case MachTrap gets an
  826.      * overflow.  But we won't get one since this is an underflow trap.
  827.      * %o5 also appears to be safe here since it is not overwritten
  828.      * by parameters to Vm_PageIn, etc.  We also need 2 more globals for
  829.      * checking whether the stack will cause a fault.  We use a few more
  830.      * out registers that we hope Vm_PageIn won't trash. NOTE:  WE ARE
  831.      * MAKING AN ASSUMPTION that Vm_PageIn isn't compiled to mess with its
  832.      * in registers.  If we switch compilers, this may break!!!
  833.      */
  834.     mov    %g3, %SAFE_TEMP
  835.     mov    %g4, %o5
  836.     mov    %g2, %o3
  837.     mov    %g5, %o4
  838.  
  839.     /* Test if we came from user mode. */
  840.     andcc    %CUR_PSR_REG, MACH_PS_BIT, %g0
  841.     bne    NormalUnderflow
  842.     nop
  843.  
  844.     /*
  845.      * Test if stack is resident for window we need to restore.
  846.      * This means move back a window and test its frame pointer since
  847.      * we've trapped into a window 2 away from the one whose stack is
  848.      * in question.
  849.      */
  850.     restore
  851.     /*
  852.      * If the alignment of the user stack pointer is bad, kill the process!
  853.      * We must be back in the trap window to do that.
  854.      */
  855.     andcc    %fp, 0x7, %g0
  856.     be,a    CheckForFaults
  857.     clr    %g3            /* g3 clear for no problem yet */
  858.     set    0x1, %g3        /* Mark why we will save state */
  859.     bne,a    MustSaveState
  860.     save        /* back to trap window, in annulled delay slot */
  861.  
  862. CheckForFaults:
  863.     /*
  864.      * %g3 will have have a record of what faults would occur.
  865.      */
  866.     MACH_CHECK_STACK_FAULT(%fp, %g2, %g3, %g5, UndflFault1, UndflFault2)
  867.     mov    %fp, %g4        /* in case we need to fault it */
  868.     be    NormalUnderflow
  869.     save                /* back to trap window */
  870.  
  871. MustSaveState:
  872.     /*
  873.      * We need to save state.   We must do this in actual trap window.
  874.      * This state-saving enables traps.  We will return to
  875.      * MachReturnToUnderflowWithSavedState
  876.      */
  877.     call    _MachTrap
  878.     nop
  879. MachReturnToUnderflowWithSavedState:
  880.     /*
  881.      * We had to save state for some reason.  %g3 contains the reason
  882.      * why.
  883.      */
  884.     cmp    %g3, 0x1
  885.     be    KillTheProc
  886.     nop
  887.     andcc    %g3, 0x2, %g0
  888.     be    CheckNextUnderflow    /* It wasn't first possible fault */
  889.     nop
  890.  
  891.     QUICK_ENABLE_INTR(%VOL_TEMP1)
  892.     /* Address that would fault is in %g4. */
  893.     mov    %g4, %o0
  894.     clr    %o1            /* also check protection???? */
  895.     call    _Vm_PageIn, 2
  896.     nop
  897.     QUICK_DISABLE_INTR(%VOL_TEMP1)
  898.     tst    %RETURN_VAL_REG
  899.     be    CheckNextUnderflow        /* succeeded, try next */
  900.     nop
  901.     /* Otherwise, bad return, fall through to kill process. */
  902. KillTheProc:
  903.     /* Need I restore all the global registers here since it's dying? */
  904.  
  905.     mov    %SAFE_TEMP, %g3            /* restore g3 */
  906.     mov    %o5, %g4            /* restore g4 */
  907.     mov    %o3, %g2            /* etc */
  908.     mov    %o4, %g5
  909.  
  910.     /* KILL IT - must be in trap window */
  911.     MACH_SR_HIGHPRIO()    /* traps back on for overflow from printf */
  912.     set    _MachHandleWindowUnderflowDeathString, %o0
  913.     call    _printf, 1
  914.     nop
  915.     MACH_GET_CUR_PROC_PTR(%o0)        /* procPtr in %o0 */
  916.     set    _machGenFlagsOffset, %o1
  917.     ld    [%o1], %o1
  918.     add    %o0, %o1, %o1
  919.     ld    [%o1], %o1
  920.     set    _machForeignFlag, %o2
  921.     ld    [%o2], %o2
  922.     andcc    %o1, %o2, %o1            /* Is this a migrated proc? */
  923.     be    SuspendIt
  924.     nop
  925.     set    PROC_TERM_DESTROYED, %o0    /* If so, kill it. */
  926.     set    PROC_BAD_STACK, %o1
  927.     clr    %o2
  928.     call    _Proc_ExitInt, 3
  929.     nop
  930. SuspendIt:                    /* Else, make it debuggable. */
  931.     MACH_GET_CUR_PROC_PTR(%o0)        /* procPtr in %o0 */
  932.     call    _Sig_CheckForKill, 1        /* kill proc if KILL signal */
  933.     nop
  934.     MACH_GET_CUR_PROC_PTR(%o0)        /* procPtr in %o0 */
  935.     set    TRUE, %o1            /* debug TRUE */
  936.     set    PROC_TERM_DESTROYED, %o2
  937.     set    PROC_BAD_STACK, %o3
  938.     clr    %o4
  939.     call    _Proc_SuspendProcess, 5
  940.     nop
  941.     ba    SuspendIt        /* proc should loop if continued */
  942.     nop
  943.  
  944. CheckNextUnderflow:
  945.     andcc    %g3, 0x4, %g0        /* See if second address would fault */
  946.     be    BackAgain
  947.     nop
  948.     QUICK_ENABLE_INTR(%VOL_TEMP1)
  949.     /* old %fp is in %g4 */
  950.     add    %g4, (MACH_SAVED_WINDOW_SIZE - 4), %o0
  951.     clr    %o1            /* also check protection???? */
  952.     call    _Vm_PageIn, 2
  953.     nop
  954.     QUICK_DISABLE_INTR(%VOL_TEMP1)
  955.     tst    %RETURN_VAL_REG
  956.     bne    KillTheProc
  957.     nop
  958. BackAgain:
  959.     /*
  960.      * Don't deal with underflow itself.  Just pretend this was only
  961.      * a stack page fault.  User's restore instruction will get
  962.      * re-executed and will cause a further underflow trap.  This time,
  963.      * the page should be there.
  964.      */
  965.  
  966.     /* Restore globals */
  967.     mov    %SAFE_TEMP, %g3            /* restore g3 and g4 */
  968.     mov    %o5, %g4
  969.     mov    %o3, %g2
  970.     mov    %o4, %g5
  971.  
  972.     call    _MachReturnFromTrap
  973.     nop
  974.  
  975. NormalUnderflow:
  976.     restore                    /* retreat a window */
  977.     /*
  978.      * We need to preserve l6 and l7 in this window
  979.      */
  980.     mov    %l6, %g2
  981.     mov    %l7, %g5
  982.     mov    %RETURN_ADDR_REG, %g3        /* save reg in global */
  983.     set    MachWindowUnderflow, %g4    /* put address in global */
  984.     jmpl    %g4, %RETURN_ADDR_REG        /* our return addr to reg */
  985.     nop
  986.     mov    %g3, %RETURN_ADDR_REG        /* restore ret_addr */
  987.     mov    %g2, %l6
  988.     mov    %g5, %l7
  989.     save                    /* back to trap window */
  990.  
  991.     /* Restore globals */
  992.     mov    %SAFE_TEMP, %g3            /* restore g3, g4, g2 & g5 */
  993.     mov    %o5, %g4
  994.     mov    %o3, %g2
  995.     mov    %o4, %g5
  996.  
  997.     MACH_RESTORE_PSR()            /* restore psr */
  998.     jmp    %CUR_PC_REG            /* return from trap */
  999.     rett    %NEXT_PC_REG
  1000.     nop
  1001.  
  1002.  
  1003. /*
  1004.  * ----------------------------------------------------------------------
  1005.  *
  1006.  * MachWindowUnderflow --
  1007.  *
  1008.  *    Window underflow handler.  It's set up so that it can be called as a
  1009.  *    result of a window underflow trap or as a result of needing to restore
  1010.  *    an invalid window before returning from a trap or interrupt.
  1011.  *    The address of the calling instruction is stored in %RETURN_ADDR_REG,
  1012.  *    which is the normal place.
  1013.  *
  1014.  *    The window we are in when we enter is one beyond the invalid window we
  1015.  *    need to restore. On an underflow trap we enter the kernel 2 windows
  1016.  *    away from the window that is invalid.  (This is because we tried to
  1017.  *    retreat to an invalid window and couldn't, so we trapped.  Trapping
  1018.  *    advances the current window, so we are 2 windows away from the invalid
  1019.  *    window.)  From the trap handler, then, we must retreat one window
  1020.  *    before calling this routine so that we're only one window away from
  1021.  *    the invalid window.  Then after returning from here, we must do a
  1022.  *    save to get back to our old trap window.
  1023.  *
  1024.  *    First we mark the window behind the invalid window as the
  1025.  *    new invalid window, and then we move to the invalid window.  Then we
  1026.  *    restore data from the stack into the invalid window.  Then we return
  1027.  *    to our previous window.  Note that we first mark
  1028.  *    the new invalid window and then move to the old invalid window.  If
  1029.  *    we did this in the other order, we'd get another window underflow trap.
  1030.  *    (This is the opposite order from window overflow.)
  1031.  *
  1032.  *    For the window to restore, the %sp should be good since it doesn't
  1033.  *    get changed by these routines, even if it was a user window and this
  1034.  *    is a kernel window.
  1035.  *
  1036.  *    The %sp should point to highest (on stack, lowest in memory)
  1037.  *    usable word in the current stack frame.  %fp is the %sp of the
  1038.  *    caller's stack frame, so the first (highest in memory) usable word
  1039.  *    of a current stack frame is (%fp - 4).
  1040.  *
  1041.  * Results:
  1042.  *    None.
  1043.  *
  1044.  * Side effects:
  1045.  *    The window invalid mask changes and a register window is restored.
  1046.  *
  1047.  * ----------------------------------------------------------------------
  1048.  */
  1049. .global    MachWindowUnderflow
  1050. MachWindowUnderflow:
  1051.     /*
  1052.      * Check to see if we're about to return to the trap window from
  1053.      * the debugger.  If so, then the frame pointer should be equal
  1054.      * to the base of the debugger stack.  If it is, change it to be
  1055.      * the top of the regular stack, so that when we return to the previous
  1056.      * window, our sp is at the top of the regular stack.
  1057.      * NOTE: The test below must agree with the amount we bump up the stack
  1058.      * by in MachTrap.
  1059.      */
  1060.     set    _machDebugStackStart, %VOL_TEMP1
  1061.     ld    [%VOL_TEMP1], %VOL_TEMP1        /* base of stack */
  1062.     set    MACH_FULL_STACK_FRAME, %VOL_TEMP2
  1063.     sub    %VOL_TEMP1, %VOL_TEMP2, %VOL_TEMP1    /* offset from base */
  1064.     cmp    %VOL_TEMP1, %fp
  1065.     bne    RegularStack
  1066.     nop
  1067.  
  1068. DealWithDebugStack:
  1069.     /* Set stack pointer of next window to regular frame pointer */
  1070.     set    _machSavedRegisterState, %VOL_TEMP1
  1071.     ld    [%VOL_TEMP1], %fp
  1072.     
  1073. RegularStack:
  1074.     /*
  1075.      * We assume that by the time we've gotten here, the stack has been
  1076.      * made resident, if it was a user stack, and we can just go blasting
  1077.      * ahead.
  1078.      *
  1079.      * It should be ok to use locals here - it's a dead window.
  1080.      * Note that this means one cannot do a restore and then a save
  1081.      * and expect that the old locals in the dead window are still the
  1082.      * same.  That would be a really dumb thing to think anyway.
  1083.      */
  1084.     /* mark new invalid window */
  1085.     MACH_RETREAT_WIM(%VOL_TEMP1, %VOL_TEMP2, underflowLabel)
  1086.  
  1087.     /* move to window to restore */
  1088.     restore
  1089.     /* restore data from stack to window - stack had better be resident! */
  1090.     MACH_RESTORE_WINDOW_FROM_STACK()
  1091.     /* Move back to previous window.   Clear registers too??? */
  1092.     save
  1093.     /*
  1094.      * jump to calling routine - this may be a trap-handler or not.
  1095.      */
  1096.     jmp    %RETURN_ADDR_REG + 8
  1097.     nop
  1098.  
  1099.  
  1100.  
  1101. /*
  1102.  * ----------------------------------------------------------------------
  1103.  *
  1104.  * MachHandleDebugTrap --
  1105.  *
  1106.  *    Enter the debugger.  This means make sure all the windows are
  1107.  *    saved to the stack, save my stack pointer, switch the stack pointer
  1108.  *    to the debugger stack, and go.
  1109.  *
  1110.  *    When we return, we change stack pointers and go to the usual
  1111.  *    return from trap routine.
  1112.  *
  1113.  * Results:
  1114.  *    None.
  1115.  *
  1116.  * Side effects:
  1117.  *    None.
  1118.  *
  1119.  * ----------------------------------------------------------------------
  1120.  */
  1121. .global    _MachHandleDebugTrap
  1122. _MachHandleDebugTrap:
  1123.     /*
  1124.      * If we came from user mode, we do different stuff.
  1125.      */
  1126.         andcc   %CUR_PSR_REG, MACH_PS_BIT, %g0         /* previous state? */
  1127.         bne    KernelDebug                 /* was kernel mode */
  1128.     nop
  1129.     call    _MachUserDebug
  1130.     nop
  1131.     set    _MachReturnFromTrap, %VOL_TEMP1
  1132.     jmp    %VOL_TEMP1
  1133.     nop
  1134. KernelDebug:
  1135.     /*
  1136.      * This points to the top stack frame, which consists of a
  1137.      * Mach_RegState structure.  This is handed to the debugger.  We
  1138.      * also use this to restore our stack pointer upon returning from the
  1139.      * debugger.
  1140.      */
  1141.     set    _machSavedRegisterState, %VOL_TEMP1
  1142.     st    %sp, [%VOL_TEMP1]
  1143.     /*
  1144.      * Now make sure all windows are flushed to the stack.  We do this
  1145.      * with MACH_NUM_WINDOWS - 1 saves and restores.  The window overflow
  1146.      * and underflow traps will then handle this for us.  We put the counter
  1147.      * in a global, since they have all been saved already and are free
  1148.      * for our use and we need the value across windows.
  1149.      */
  1150.     set    (MACH_NUM_WINDOWS - 1), %g1
  1151. SaveSomeMore:
  1152.     save
  1153.     subcc    %g1, 1, %g1
  1154.     bne    SaveSomeMore
  1155.     nop
  1156.     set    (MACH_NUM_WINDOWS - 1), %g1
  1157. RestoreSomeMore:
  1158.     restore
  1159.     subcc    %g1, 1, %g1
  1160.     bne    RestoreSomeMore
  1161.     nop
  1162.     /* Set stack base for debugger */
  1163.     set    _machDebugStackStart, %VOL_TEMP1
  1164.     ld    [%VOL_TEMP1], %VOL_TEMP1        /* stack base */
  1165.     set    MACH_FULL_STACK_FRAME, %VOL_TEMP2
  1166.     sub    %VOL_TEMP1, %VOL_TEMP2, %sp        /* offset from base */
  1167.     /* get trap type into o0 from local saved value */
  1168.     and    %CUR_TBR_REG, MACH_TRAP_TYPE_MASK, %o0
  1169.     srl    %o0, 4, %o0
  1170.     /* put saved reg ptr into o1 */
  1171.     set    _machSavedRegisterState, %VOL_TEMP1
  1172.     ld    [%VOL_TEMP1], %o1
  1173.     /*
  1174.      * Set wim to this window, so that when we return from debugger,
  1175.      * we'll restore the registers for this window from the stack state
  1176.      * handled by the debugger.  This is safe to do before calling the
  1177.      * debugger, since we just saved all the windows to the stack.
  1178.      */
  1179.     MACH_SET_WIM_TO_CWP()
  1180.     /*
  1181.      * Is there a window of vulnerability here when the sp doesn't match
  1182.      * what's saved on the stack and I might restore incorrectly from
  1183.      * stack if I took another trap?  But interrupts should be off and
  1184.      * I shouldn't get a trap.
  1185.      */
  1186.  
  1187.     /* call debugger */
  1188.     call    _Dbg_Main,2
  1189.     nop
  1190.  
  1191.     /* put saved stack pointer into %sp. */
  1192.     set    _machSavedRegisterState, %VOL_TEMP1
  1193.     ld    [%VOL_TEMP1], %sp
  1194.  
  1195.     /* finish as for regular trap */
  1196.     set    _MachReturnFromTrap, %VOL_TEMP1
  1197.     jmp    %VOL_TEMP1
  1198.     nop
  1199.  
  1200.  
  1201. /*
  1202.  * ----------------------------------------------------------------------
  1203.  *
  1204.  * MachSyscallTrap --
  1205.  *
  1206.  *    This is the code to handle system call traps.  The number of the
  1207.  *    system call is in %g1.
  1208.  *
  1209.  * Results:
  1210.  *    Returns a status to the caller in the caller's %o0 (or %i0).
  1211.  *
  1212.  * Side effects:
  1213.  *    Depends on the kernel call.
  1214.  *
  1215.  * ----------------------------------------------------------------------
  1216.  */
  1217. .global    MachSyscallTrap
  1218. MachSyscallTrap:
  1219.     /*
  1220.      * So that we don't re-execute the trap instruction when we
  1221.      * return from the system call trap via the return trap procedure,
  1222.      * we increment the return pc and npc here.
  1223.      */
  1224.     mov    %NEXT_PC_REG, %CUR_PC_REG
  1225.     add    %NEXT_PC_REG, 0x4, %NEXT_PC_REG
  1226.     /*
  1227.      * Make sure user stack pointer is written into state structure so that
  1228.      * it can be used while processing the system call.  (Who uses it??)
  1229.      * This means saving the frame pointer (previous user stack pointer).
  1230.      */
  1231.     MACH_GET_CUR_STATE_PTR(%VOL_TEMP1, %VOL_TEMP2)    /* into %VOL_TEMP1 */
  1232.     add    %VOL_TEMP1, MACH_TRAP_REGS_OFFSET, %VOL_TEMP1
  1233.     ld    [%VOL_TEMP1], %VOL_TEMP1
  1234.     add    %VOL_TEMP1, MACH_FP_OFFSET, %VOL_TEMP1
  1235.     st    %fp, [%VOL_TEMP1]
  1236.     /* If fork call, save registers and invalidate trapRegs stuff????? */
  1237.     /*
  1238.      * Check number of kernel call for validity.  This was stored in %g1.
  1239.      * We must be careful not to have trashed it.  But if we end up
  1240.      * trashing it, we could instead pull it out of the saved globals state
  1241.      * in the mach state structure since it got saved there.
  1242.      */
  1243.     set    _machMaxSysCall, %VOL_TEMP1
  1244.     ld    [%VOL_TEMP1], %VOL_TEMP1
  1245.     cmp    %VOL_TEMP1, %g1
  1246.     bgeu    GoodSysCall
  1247.     nop
  1248.     /*
  1249.      * If bad, (take user error? - on spur) then do normal return from trap.
  1250.      * Is this magic number a return value?  It's in the sun3 code.
  1251.      */
  1252.     set    SYS_INVALID_SYSTEM_CALL, %RETURN_VAL_REG
  1253.     set    ReturnFromSyscall, %VOL_TEMP1
  1254.     jmp    %VOL_TEMP1
  1255.     nop
  1256. GoodSysCall:
  1257.     /*
  1258.      * Save sys call number into lastSysCall field in process state so
  1259.      * that migration can figure out what it was supposed to be.
  1260.      * %g1 must still contain syscall number.
  1261.      */
  1262.     MACH_GET_CUR_STATE_PTR(%VOL_TEMP1, %VOL_TEMP2)    /* into %VOL_TEMP1 */
  1263.     set    _machLastSysCallOffset, %VOL_TEMP2
  1264.     ld    [%VOL_TEMP2], %VOL_TEMP2
  1265.     add    %VOL_TEMP1, %VOL_TEMP2, %VOL_TEMP1
  1266.     st    %g1, [%VOL_TEMP1]
  1267.     /*
  1268.      * Fetch args.  Copy them from user space if they aren't all in
  1269.      * the input registers.  For now I copy all the input registers,
  1270.      * since there isn't a table giving the actual number of args?
  1271.      * For args beyond the number of words that can fit in the input
  1272.      * registers, I get the offset to copy to and the pc to jump to inside
  1273.      * the copying from tables set up in Mach_SyscallInit.  If there
  1274.      * are no args to copy, then the pc gets set to jump to
  1275.      * MachFetchArgsEnd.
  1276.      */
  1277.     mov    %i5, %o5
  1278.     mov    %i4, %o4
  1279.     mov    %i3, %o3
  1280.     mov    %i2, %o2
  1281.     mov    %i1, %o1
  1282.     mov    %i0, %o0
  1283.     /*
  1284.      * Fetch offsets to copy from and to out of table.
  1285.      */
  1286.     sll    %g1, 2, %g1                /* system call index */
  1287.     set    _machArgOffsets, %VOL_TEMP2        /* offset in table */
  1288.     add    %g1, %VOL_TEMP2, %VOL_TEMP2        /* addr in table */
  1289.     ld    [%VOL_TEMP2], %VOL_TEMP2        /* offset value */
  1290.     add    %fp, %VOL_TEMP2, %VOL_TEMP1        /* need global here? */
  1291.     add    %sp, %VOL_TEMP2, %VOL_TEMP2        /* need global here? */
  1292.  
  1293.     /*
  1294.      * Fetch pc branch address out of table and put it into %SAFE_TEMP
  1295.      */
  1296.     set    _machArgDispatch, %SAFE_TEMP
  1297.     add    %g1, %SAFE_TEMP, %SAFE_TEMP
  1298.     ld    [%SAFE_TEMP], %SAFE_TEMP
  1299.     jmp    %SAFE_TEMP
  1300.     nop
  1301.  
  1302. .global    _MachFetchArgs
  1303. _MachFetchArgs:
  1304.     ld    [%VOL_TEMP1], %SAFE_TEMP    /* first word - pc offset 0 */
  1305.     st    %SAFE_TEMP, [%VOL_TEMP2]
  1306.     add    %VOL_TEMP1, 4, %VOL_TEMP1
  1307.     add    %VOL_TEMP2, 4, %VOL_TEMP2
  1308.     ld    [%VOL_TEMP1], %SAFE_TEMP    /* second word - pc offset 16 */
  1309.     st    %SAFE_TEMP, [%VOL_TEMP2]
  1310.     add    %VOL_TEMP1, 4, %VOL_TEMP1
  1311.     add    %VOL_TEMP2, 4, %VOL_TEMP2
  1312.     ld    [%VOL_TEMP1], %SAFE_TEMP    /* third word - pc offset 32 */
  1313.     st    %SAFE_TEMP, [%VOL_TEMP2]
  1314.     add    %VOL_TEMP1, 4, %VOL_TEMP1
  1315.     add    %VOL_TEMP2, 4, %VOL_TEMP2
  1316.     ld    [%VOL_TEMP1], %SAFE_TEMP    /* fourth word */
  1317.     st    %SAFE_TEMP, [%VOL_TEMP2]
  1318.     add    %VOL_TEMP1, 4, %VOL_TEMP1
  1319.     add    %VOL_TEMP2, 4, %VOL_TEMP2
  1320.     ld    [%VOL_TEMP1], %SAFE_TEMP    /* fifth word */
  1321.     st    %SAFE_TEMP, [%VOL_TEMP2]
  1322.     add    %VOL_TEMP1, 4, %VOL_TEMP1
  1323.     add    %VOL_TEMP2, 4, %VOL_TEMP2
  1324.     ld    [%VOL_TEMP1], %SAFE_TEMP    /* sixth word */
  1325.     st    %SAFE_TEMP, [%VOL_TEMP2]
  1326.     add    %VOL_TEMP1, 4, %VOL_TEMP1
  1327.     add    %VOL_TEMP2, 4, %VOL_TEMP2
  1328.     ld    [%VOL_TEMP1], %SAFE_TEMP    /* seventh word */
  1329.     st    %SAFE_TEMP, [%VOL_TEMP2]
  1330.     add    %VOL_TEMP1, 4, %VOL_TEMP1
  1331.     add    %VOL_TEMP2, 4, %VOL_TEMP2
  1332.     ld    [%VOL_TEMP1], %SAFE_TEMP    /* eighth word */
  1333.     st    %SAFE_TEMP, [%VOL_TEMP2]
  1334.     add    %VOL_TEMP1, 4, %VOL_TEMP1
  1335.     add    %VOL_TEMP2, 4, %VOL_TEMP2
  1336.     ld    [%VOL_TEMP1], %SAFE_TEMP    /* ninth word */
  1337.     st    %SAFE_TEMP, [%VOL_TEMP2]
  1338.     add    %VOL_TEMP1, 4, %VOL_TEMP1
  1339.     add    %VOL_TEMP2, 4, %VOL_TEMP2
  1340.     ld    [%VOL_TEMP1], %SAFE_TEMP    /* tenth word */
  1341.     st    %SAFE_TEMP, [%VOL_TEMP2]
  1342.     add    %VOL_TEMP1, 4, %VOL_TEMP1
  1343.     add    %VOL_TEMP2, 4, %VOL_TEMP2
  1344.     /*
  1345.      * Marks last place where PC could be when a page fault occurs while
  1346.      * fetching arguments.  Needed to distinguish between a page fault
  1347.      * during arg fetch (which is okay) from other page faults in the
  1348.      * kernel, which are fatal errors.
  1349.      */
  1350. .global    _MachFetchArgsEnd
  1351. _MachFetchArgsEnd:
  1352.     /* get address from table */
  1353.     MACH_GET_CUR_PROC_PTR(%VOL_TEMP1)        /* into %VOL_TEMP1 */
  1354.     set    _machKcallTableOffset, %VOL_TEMP2
  1355.     ld    [%VOL_TEMP2], %VOL_TEMP2        /* offset to kcalls */
  1356.     add    %VOL_TEMP1, %VOL_TEMP2, %VOL_TEMP1
  1357.     ld    [%VOL_TEMP1], %VOL_TEMP1        /* addr of array */
  1358.     add    %g1, %VOL_TEMP1, %VOL_TEMP1        /* index to kcall */
  1359.     ld    [%VOL_TEMP1], %VOL_TEMP1        /* got addr */
  1360.     /* enable interrupts */
  1361.     QUICK_ENABLE_INTR(%VOL_TEMP2)
  1362.     /* go do it */
  1363.     call    %VOL_TEMP1
  1364.     nop
  1365. ReturnFromSyscall:
  1366.     /* Disable interrupts. */
  1367.     QUICK_DISABLE_INTR(%VOL_TEMP1)
  1368.     /*
  1369.      * Move return value to caller's return val register.
  1370.      */
  1371.     mov    %RETURN_VAL_REG, %RETURN_VAL_REG_CHILD
  1372.     /*
  1373.      * Sun3 checks special handling flag here.  I do it in return from
  1374.      * trap, if we came from a user process.
  1375.      */
  1376.  
  1377.     /* restore the stack pointers? */
  1378.  
  1379.     /* do normal return from trap */
  1380.     set    _MachReturnFromTrap, %VOL_TEMP1
  1381.     jmp    %VOL_TEMP1
  1382.     nop
  1383.  
  1384. /*
  1385.  * ----------------------------------------------------------------------
  1386.  *
  1387.  * MachLinkTrap --
  1388.  *
  1389.  *    This is the code to handle a dynamic linking trap #2.
  1390.  *    Apparently we don't have to do anything.
  1391.  *
  1392.  * Results:
  1393.  *    None.
  1394.  *
  1395.  * Side effects:
  1396.  *    None.
  1397.  *
  1398.  * ----------------------------------------------------------------------
  1399.  */
  1400. .global    MachLinkTrap
  1401. MachLinkTrap:
  1402.     /*
  1403.      * So that we don't re-execute the trap instruction when we
  1404.      * return from the system call trap via the return trap procedure,
  1405.      * we increment the return pc and npc here.
  1406.      */
  1407.     mov    %NEXT_PC_REG, %CUR_PC_REG
  1408.     add    %NEXT_PC_REG, 0x4, %NEXT_PC_REG
  1409.  
  1410.     /* do normal return from trap */
  1411.     set    _MachReturnFromTrap, %VOL_TEMP1
  1412.     jmp    %VOL_TEMP1
  1413.  
  1414. /*
  1415.  * ----------------------------------------------------------------------
  1416.  *
  1417.  * MachUnixSyscallTrap --
  1418.  *
  1419.  *    This is the code to handle unix system call traps.  The number of the
  1420.  *    system call is in %g1.
  1421.  *
  1422.  * Results:
  1423.  *    Returns a status to the caller in the caller's %o0 (or %i0).
  1424.  *
  1425.  * Side effects:
  1426.  *    Depends on the kernel call.
  1427.  *
  1428.  * ----------------------------------------------------------------------
  1429.  */
  1430. .global    MachUnixSyscallTrap
  1431. MachUnixSyscallTrap:
  1432.     /*
  1433.      * So that we don't re-execute the trap instruction when we
  1434.      * return from the system call trap via the return trap procedure,
  1435.      * we increment the return pc and npc here.
  1436.      */
  1437.     mov    %NEXT_PC_REG, %CUR_PC_REG
  1438.     add    %NEXT_PC_REG, 0x4, %NEXT_PC_REG
  1439.     /*
  1440.      * Make sure user stack pointer is written into state structure so that
  1441.      * it can be used while processing the system call.  (Who uses it??)
  1442.      * This means saving the frame pointer (previous user stack pointer).
  1443.      */
  1444.     MACH_GET_CUR_STATE_PTR(%VOL_TEMP1, %VOL_TEMP2)    /* into %VOL_TEMP1 */
  1445.     add    %VOL_TEMP1, MACH_TRAP_REGS_OFFSET, %VOL_TEMP1
  1446.     ld    [%VOL_TEMP1], %VOL_TEMP1
  1447.     add    %VOL_TEMP1, MACH_FP_OFFSET, %VOL_TEMP1
  1448.     st    %fp, [%VOL_TEMP1]
  1449.     nop
  1450.     /* If fork call, save registers and invalidate trapRegs stuff????? */
  1451.     /*
  1452.      * Check number of kernel call for validity.  This was stored in %g1.
  1453.      * We must be careful not to have trashed it.  But if we end up
  1454.      * trashing it, we could instead pull it out of the saved globals state
  1455.      * in the mach state structure since it got saved there.
  1456.      */
  1457.     set    _sysUnixNumSyscalls, %VOL_TEMP1
  1458.     ld    [%VOL_TEMP1], %VOL_TEMP1
  1459.     cmp    %VOL_TEMP1, %g1
  1460.     bgeu    GoodUnixSysCall
  1461.     nop
  1462.     /*
  1463.      * If bad, (take user error? - on spur) then do normal return from trap.
  1464.      * Is this magic number a return value?  It's in the sun3 code.
  1465.      */
  1466.     set    -1, %RETURN_VAL_REG
  1467.     set    ReturnFromUnixSyscall, %VOL_TEMP1
  1468.     jmp    %VOL_TEMP1
  1469.     nop
  1470. GoodUnixSysCall:
  1471.     /*
  1472.      * Save sys call number into lastSysCall field in process state so
  1473.      * that migration can figure out what it was supposed to be.
  1474.      * %g1 must still contain syscall number.
  1475.      */
  1476.     MACH_GET_CUR_STATE_PTR(%VOL_TEMP1, %VOL_TEMP2)    /* into %VOL_TEMP1 */
  1477.     set    _machLastSysCallOffset, %VOL_TEMP2
  1478.     ld    [%VOL_TEMP2], %VOL_TEMP2
  1479.     add    %VOL_TEMP1, %VOL_TEMP2, %VOL_TEMP1
  1480.     st    %g1, [%VOL_TEMP1]
  1481.     /*
  1482.      * Save i0 for call restart.
  1483.      */
  1484.     st    %i0, [%VOL_TEMP1+4]
  1485.     /*
  1486.      * Fetch args.  Copy them from user space if they aren't all in
  1487.      * the input registers.  For now I copy all the input registers,
  1488.      * since there isn't a table giving the actual number of args?
  1489.      * For args beyond the number of words that can fit in the input
  1490.      * registers, I get the offset to copy to and the pc to jump to inside
  1491.      * the copying from tables set up in Mach_SyscallInit.  If there
  1492.      * are no args to copy, then the pc gets set to jump to
  1493.      * MachFetchArgsEnd.
  1494.      */
  1495.     mov    %i5, %o5
  1496.     mov    %i4, %o4
  1497.     mov    %i3, %o3
  1498.     mov    %i2, %o2
  1499.     mov    %i1, %o1
  1500.     mov    %i0, %o0
  1501.  
  1502.     cmp    %g1, 0x8b /* Sigreturn */
  1503.     be    DoSigreturn
  1504.  
  1505.     sll    %g1, 3, %g1
  1506.     set    _sysUnixSysCallTable, %VOL_TEMP2
  1507.     add    %g1, %VOL_TEMP2, %VOL_TEMP2        /* index to kcall */
  1508.     ld    [%VOL_TEMP2], %VOL_TEMP2        /* got addr */
  1509.     /* enable interrupts */
  1510.     QUICK_ENABLE_INTR(%VOL_TEMP1)
  1511.     /* go do it */
  1512.     call    %VOL_TEMP2
  1513.     nop
  1514. ReturnFromUnixSyscall:
  1515.     /* Disable interrupts. */
  1516.     QUICK_DISABLE_INTR(%VOL_TEMP1)
  1517.     /*
  1518.      * Move return value to caller's return val register.
  1519.      */
  1520.  
  1521.     /*
  1522.      * Check if error.
  1523.      */
  1524.     cmp    %RETURN_VAL_REG, -1
  1525.     bne    UnixOk
  1526.     nop
  1527.  
  1528.     /*
  1529.      * Get the errno from the pcb and use it as the return value.
  1530.      */
  1531.     MACH_GET_CUR_PROC_PTR(%VOL_TEMP1)        /* into %VOL_TEMP1 */
  1532.     set    MACH_UNIX_ERRNO_OFFSET, %VOL_TEMP2
  1533.     add    %VOL_TEMP1, %VOL_TEMP2, %VOL_TEMP1
  1534.     ld    [%VOL_TEMP1], %VOL_TEMP1
  1535.     mov    %VOL_TEMP1, %RETURN_VAL_REG_CHILD
  1536.  
  1537.     /*
  1538.      * Set the carry to indicate an error.
  1539.      */
  1540.     mov    %CUR_PSR_REG, %VOL_TEMP2
  1541.     set    MACH_CARRY_BIT, %VOL_TEMP1
  1542.     or    %VOL_TEMP2, %VOL_TEMP1, %VOL_TEMP2
  1543.     mov    %VOL_TEMP2, %CUR_PSR_REG
  1544.     set    _MachReturnFromTrap, %VOL_TEMP1
  1545.     jmp    %VOL_TEMP1
  1546.     nop
  1547.  
  1548. UnixOk:
  1549.     mov    %RETURN_VAL_REG, %RETURN_VAL_REG_CHILD
  1550.     mov    %o1, %i1
  1551.     mov    %CUR_PSR_REG, %VOL_TEMP2
  1552.     set    MACH_CARRY_BITMASK, %VOL_TEMP1
  1553.     and    %VOL_TEMP2, %VOL_TEMP1, %VOL_TEMP2
  1554.     mov    %VOL_TEMP2, %CUR_PSR_REG
  1555.     set    _MachReturnFromTrap, %VOL_TEMP1
  1556.     jmp    %VOL_TEMP1
  1557.     nop
  1558.  
  1559. DoSigreturn:
  1560.     /* We have to skip the errno checking */
  1561.     QUICK_ENABLE_INTR(%VOL_TEMP1)
  1562.     /* go do it */
  1563.     call    _Mach_SigreturnStub
  1564.     nop
  1565.     MACH_RESTORE_WINDOW_FROM_STACK()
  1566.     /* Disable interrupts. */
  1567.     QUICK_DISABLE_INTR(%VOL_TEMP1)
  1568.     set    _MachReturnFromTrap, %VOL_TEMP1
  1569.     jmp    %VOL_TEMP1
  1570.     nop
  1571.  
  1572.  
  1573. /*
  1574.  * ----------------------------------------------------------------------
  1575.  *
  1576.  * MachHandlePageFault --
  1577.  *
  1578.  *    An instruction or data fault has occurred.  This routine will retrieve
  1579.  *    the fault error from the bus error register and the faulting address
  1580.  *    from the address error register and will call
  1581.  *    Vm routines to handle faulting in the page.
  1582.  *
  1583.  * Results:
  1584.  *    Returns to MachReturnFromTrap rather than its caller.
  1585.  *
  1586.  * Side effects:
  1587.  *    The page that caused the fault will become valid.
  1588.  *
  1589.  * ----------------------------------------------------------------------
  1590.  */
  1591. .global MachHandlePageFault
  1592. MachHandlePageFault:
  1593. #ifdef sun4c
  1594.     /* synchronous error register value as first arg - clears it too. */
  1595.     set    VMMACH_SYNC_ERROR_REG, %o0
  1596.     lda    [%o0] VMMACH_CONTROL_SPACE, %o0
  1597.  
  1598.     /* synch error address register value as second arg - clears it. */
  1599.     set    VMMACH_SYNC_ERROR_ADDR_REG, %o1
  1600.     lda    [%o1] VMMACH_CONTROL_SPACE, %o1
  1601.  
  1602.     /* clear async regs as well since they latch on sync errors as well. */
  1603.     set    VMMACH_ASYNC_ERROR_REG, %VOL_TEMP1
  1604.     lda    [%VOL_TEMP1] VMMACH_CONTROL_SPACE, %g0
  1605.  
  1606.     /* async error addr reg as well, so clear it.  Very silly. */
  1607.     set    VMMACH_ASYNC_ERROR_ADDR_REG, %VOL_TEMP1
  1608.     lda    [%VOL_TEMP1] VMMACH_CONTROL_SPACE, %g0
  1609. #else
  1610.     /* bus error register value as first arg. */
  1611.     set    VMMACH_BUS_ERROR_REG, %o0
  1612.     lduba    [%o0] VMMACH_CONTROL_SPACE, %o0
  1613.  
  1614.     /* memory address causing the error as second arg */
  1615.     set    VMMACH_ADDR_ERROR_REG, %o1
  1616.     ld    [%o1], %o1
  1617.  
  1618.     /* Write the address register to clear it */
  1619.     set    VMMACH_ADDR_ERROR_REG, %VOL_TEMP1
  1620.     st    %o1, [%VOL_TEMP1]
  1621. #endif
  1622.     /* trap value of the psr as third arg */
  1623.     mov    %CUR_PSR_REG, %o2    
  1624.  
  1625.     /* trap value of pc as fourth argument */
  1626.     mov    %CUR_PC_REG, %o3
  1627. #ifndef sun4c
  1628.     /*
  1629.      * If the trap was on a pc access rather than a data access, the
  1630.      * memoory address register won't have frozen the correct address.
  1631.      * Just move the pc into the second argument.
  1632.      */
  1633.     and    %CUR_TBR_REG, MACH_TRAP_TYPE_MASK, %VOL_TEMP1
  1634.     cmp    %VOL_TEMP1, MACH_INSTR_ACCESS
  1635.     bne    AddressValueOkay
  1636.     nop
  1637.     mov    %CUR_PC_REG, %o1
  1638. #endif
  1639. AddressValueOkay:
  1640.     /* enable interrupts */
  1641.     QUICK_ENABLE_INTR(%VOL_TEMP1)
  1642.     call    _MachPageFault, 4
  1643.     nop
  1644.     /* Disable interrupts. */
  1645.     QUICK_DISABLE_INTR(%VOL_TEMP1)
  1646.  
  1647.     set    _MachReturnFromTrap, %VOL_TEMP1
  1648.     jmp    %VOL_TEMP1
  1649.     nop
  1650.  
  1651.  
  1652. /*
  1653.  * ----------------------------------------------------------------------
  1654.  *
  1655.  * MachFlushWindowsToStackTrap --
  1656.  *
  1657.  *    A trap requesting that all our windows be flushed to the stack has
  1658.  *    occured.  Bump up our return pc, since we don't want to re-execute
  1659.  *    the trap, and then call the appropriate routine.
  1660.  *
  1661.  * Results:
  1662.  *    Returns to MachReturnFromTrap, rather than our caller.
  1663.  *
  1664.  * Side effects:
  1665.  *    Register windows will be flushed to the stack and the invalid
  1666.  *    window mask will be set to point to the window before us.
  1667.  *
  1668.  * ----------------------------------------------------------------------
  1669.  */
  1670. .global    MachFlushWindowsToStackTrap
  1671. MachFlushWindowsToStackTrap:
  1672.     mov    %NEXT_PC_REG, %CUR_PC_REG
  1673.     add    %NEXT_PC_REG, 4, %NEXT_PC_REG
  1674.     call    _Mach_FlushWindowsToStack
  1675.     nop
  1676.     set    _MachReturnFromTrap, %VOL_TEMP1
  1677.     jmp    %VOL_TEMP1
  1678.     nop
  1679.